package lift_simulator;
/**
 * 最上部に位置する、シミュレーターを実行・管理するオブジェクトです。
 * @author Yone6379univ
 *
 */
public class LiftSimulator {
	/**
	 * シミュレーター上の時間を管理するオブジェクトです。<br>
	 * TODO 今回は時間オブジェクトは１つですが、今後拡張する可能性もあるので、<br>
	 * 各オブジェクトがこのオブジェクトを利用する場合は委譲的なメソッドを作ることにします。
	 */
    public Clock clock;
    /**
     * ビルオブジェクトです。今回は１つです。
     */
    private Building building;
    /**
	 * シミュレーター上の入出力を管理するオブジェクトです。<br>
	 * TODO 今回はオブジェクトは１つですが、今後拡張する可能性もあるので、<br>
	 * 各オブジェクトがこのオブジェクトを利用する場合は委譲的なメソッドを作ることにします。
	 */
    public CsvManager csvManager;

    public static void main(String[] args) {
    	//問題１
    	//Setting setting = new Setting("no5/input_i.csv", "no5/output_i.csv", 1, 1, 10, new LiftManagerNormal());
    	//問題３
    	//Setting setting = new Setting("no5/input_iii_iv.csv", "no5/output_iii_iv.csv", 1, 5, 10, new LiftManagerNormal());
    	//問題４
    	Setting setting = new Setting("src/lift_simulator/input_iii_iv.csv", "src/lift_simulator/output_iii_iv.csv", 2, 5, 10, new LiftManagerNormal(),50);
    	new LiftSimulator(setting);
	}
    
    public LiftSimulator(Setting setting) {
    	init(setting);
    	run(setting.getSimulatorTime());
    	csvManager.check(setting.getOutputPath());
	}
    /**
     * シミュレーションに必要なオブジェクトを初期化します。
     * これ以下のプログラムを変更する必要はありません。
     * @param s
     */
    public void init(Setting s){
    	//各種初期化
    	clock = new Clock(-1);
    	csvManager = new CsvManager(s.getInputPath(), s.getOutputPath());
    	building = new Building(s.getLiftNum(), s.getLiftCapacity(), s.getFloorNum(), s.getLiftManager(),csvManager,clock);

    	//floorにタスクをセットする
    	building.setTasks(csvManager.importCsv());

    	//各リフトに最初のaimを設定する
    	building.initStatus();
    }

    /**
     * シミュレーションを開始します。
     * @param sleepTime 単位時間(仮想的な1秒)ごとに何ミリ秒待機するか。<br>
     * つまり(sleepTime=1000)で一応現実世界と同じスピードで動作する。<br>
     * 実際はプログラムによる遅延が発生するため、完全に一致はしない。<br>
     * 完全に一致することも可能(プログラムにかかった時間をsleepする時間から引く)だが、<br>
     * 時間があれば実装する
     */
    public void run(int sleepTime){
    	while(true){
    		update();
    		if(building.isFinished())
    			break;
    		try {
				Thread.sleep(sleepTime);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
    	}
    }
    /**
     * 単位時間ごとにシミュレーションの状態を更新するメソッドです。<br>
     * 更新の流れは以下のようになっています。<br>
     * 1.時間を更新({@link Clock#next()})<br>
     * 2.ビルの状態を更新({@link Building#updateStatus()})<br>
     */
    public void update(){
    	clock.next();
    	building.updateStatus();
    }

}
